/*
 Copyright (c) 2013 MeherTJ G. All rights reserved.
 License: LGPL for personnal study or free software.
 */

#pragma once

#include <string>
#include <map>
#include <memory>

namespace Zen {
	/// _SharedValue was like std::shared_ptr<?>
	template<typename _Key, typename _SharedValue>
	class Cache {
		
	public:
		Cache() = default;

		virtual ~Cache() = default;

		_SharedValue load(_Key const & key)
		{
			auto iter = m_cache.find(key);
			if(iter == m_cache.end()) {
				return onCacheNotFound(key);
			}
			return iter->second;
		}

		void cache(_Key const & key, _SharedValue v)
		{
			if(v == nullptr) m_cache.erase(key);
			else m_cache[key] = v;
		}

		void clearCache(bool include_used = false)
		{
			if(include_used)
			{
				m_cache.clear();
			}
			else
			{
				for(auto iter = m_cache.begin(); iter != m_cache.end();)
				{
					if(iter->second.use_count() == 1)
					{
						iter = m_cache.erase(iter);
					}
					else ++iter;
				}
			}
		}

	protected:
		std::map<_Key, _SharedValue> m_cache;

		virtual _SharedValue onCacheNotFound(_Key const & key) = 0;
	};
}
